package com.webinsky.article.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.webinsky.article.domain.MisArticle;
import com.webinsky.article.domain.MisArticleFilter;
import com.webinsky.article.domain.MisArticleFlowDescription;
import com.webinsky.article.domain.MisArticleImage;
import com.webinsky.article.domain.MisArticleOpSample;
import com.webinsky.article.domain.MisArticleRelate;
import com.webinsky.article.domain.MisArticleRelateVideo;
import com.webinsky.article.domain.MisArticleTag;
import com.webinsky.article.domain.MisArticleType;
import com.webinsky.article.domain.MisArticleVideo;
import com.webinsky.article.domain.MisArticles;
import com.webinsky.article.domain.MisExcelArticle;
import com.webinsky.article.persist.dao.ArticleBodyMapper;
import com.webinsky.article.persist.dao.ArticleImageMapper;
import com.webinsky.article.persist.dao.ArticleIndexMapper;
import com.webinsky.article.persist.dao.ArticleMapper;
import com.webinsky.article.persist.dao.ArticleRelateMapper;
import com.webinsky.article.persist.dao.ArticleRelateVideoMapper;
import com.webinsky.article.persist.dao.ArticleTagMapper;
import com.webinsky.article.persist.dao.ArticleVideoMapper;
import com.webinsky.article.persist.entity.Article;
import com.webinsky.article.persist.entity.ArticleBody;
import com.webinsky.article.persist.entity.ArticleImage;
import com.webinsky.article.persist.entity.ArticleIndex;
import com.webinsky.article.persist.entity.ArticleRelate;
import com.webinsky.article.persist.entity.ArticleRelateVideo;
import com.webinsky.article.persist.entity.ArticleTag;
import com.webinsky.article.persist.entity.ArticleUser;
import com.webinsky.article.persist.entity.ArticleVideo;
import com.webinsky.article.service.ArticleManagement;
import com.webinsky.common.proj.DelFlag;
import com.webinsky.common.proj.Lang;

@Service
public class ArticleManagementImpl implements ArticleManagement {
	private static final Logger logger = LoggerFactory.getLogger(ArticleManagementImpl.class);
	@Autowired
	private ArticleMapper articleDao;
	@Autowired
	private ArticleIndexMapper articleIndexDao;
	@Autowired
	private ArticleBodyMapper articleBodyDao;
	@Autowired
	private ArticleVideoMapper articleVideoDao;
	@Autowired
	private ArticleRelateMapper articleRelateDao;
	@Autowired
	private ArticleRelateVideoMapper articleRelateVideoDao;
	@Autowired
	private ArticleTagMapper articleTagDao;
	@Autowired
	private ArticleImageMapper articleImageDao;
	
	///////////////////////////////////////////////////////
	// convert
	
	private MisArticle convert(ArticleUser articleUser){
		MisArticle misArticle = new MisArticle();
		misArticle.setId(articleUser.getId());
		misArticle.setSiteId(articleUser.getSiteId());
		misArticle.setLang(Lang.parse(articleUser.getLanguage()));
		misArticle.setArticleNo(articleUser.getArticleNo());
		misArticle.setCreator(articleUser.getName());
		misArticle.setTitle(articleUser.getTitle());
		misArticle.setUpdateAt(articleUser.getUpdateAt());
		misArticle.setRemark(articleUser.getRemark());
		misArticle.setFileName(articleUser.getFileName());
		misArticle.setSummary(articleUser.getSummary());
		misArticle.setUpdateAt(articleUser.getUpdateAt());
		misArticle.setUpdateById(articleUser.getUpdateUserId());
		misArticle.setUpdateBy(articleUser.getUpdateUserName());
		misArticle.setUserId(articleUser.getUserId());
		misArticle.setCanModify(articleUser.getCanModify());
		return misArticle;
	}
	
	private MisArticle convert(Article article){
		MisArticle misArticle = new MisArticle();
		misArticle.setId(article.getId());
		misArticle.setArticleNo(article.getArticleNo());
		misArticle.setSiteId(article.getSiteId());
		misArticle.setFileName(article.getFileName());
		misArticle.setLang(Lang.parse(article.getLanguage()));
		misArticle.setRemark(article.getRemark());
		misArticle.setSummary(article.getAbs());
		misArticle.setTitle(article.getTitle());
		misArticle.setUserId(article.getUserId());
		misArticle.setUpdateAt(article.getCreateAt());
		return misArticle;
	}
	
	private MisArticleFlowDescription convert(ArticleIndex index){
		MisArticleFlowDescription mfd = new MisArticleFlowDescription();
		mfd.setId(index.getId());
		mfd.setArticleId(index.getArticleId());
		mfd.setDel(DelFlag.parse(index.getDel()));
		mfd.setIndex(index.getSort());
		mfd.setLang(Lang.parse(index.getLanguage()));
		mfd.setTilte(index.getIndexName());
		return mfd;
	}
	
	private MisArticleOpSample convert(ArticleBody body){
		MisArticleOpSample opSample = new MisArticleOpSample();
		opSample.setArticleId(body.getArticleId());
		opSample.setId(body.getId());
		opSample.setContent(body.getContent());
		opSample.setLang(Lang.parse(body.getLanguage()));
		opSample.setDel(DelFlag.parse(body.getDel()));
		opSample.setTips(body.getTips());
		opSample.setTipsColor(body.getTipsColor());
		return opSample;
	}
	
	private Article convert(MisArticle misArticle){
		Article article = new Article();
		article.setAbs(misArticle.getSummary());
		article.setArticleNo(misArticle.getArticleNo());
		article.setTitle(misArticle.getTitle());
		article.setRemark(misArticle.getRemark());
		article.setFileName(misArticle.getFileName());
		article.setSiteId(misArticle.getSiteId());
		article.setLanguage(misArticle.getLang().getLang());
		article.setUserId(misArticle.getUserId());
		if ( misArticle.getDel() != null ){
			article.setDel(misArticle.getDel().getFlag());
		}
		return article;
	}
	
	private ArticleIndex convert(MisArticleFlowDescription description){
		ArticleIndex index = new ArticleIndex();
		index.setId(description.getId());
		index.setArticleId(description.getArticleId());
		index.setIndexName(description.getTilte());
		index.setSort(description.getIndex());
		index.setLanguage(description.getLang().getLang());
		if ( description.getDel() != null ){
			index.setDel(description.getDel().getFlag());
		}
		return index;
	}
	
	private ArticleBody convert(MisArticleOpSample opSample){
		ArticleBody articleBody = new ArticleBody();
		articleBody.setId(opSample.getId());
		articleBody.setArticleId(opSample.getArticleId());
		articleBody.setContent(opSample.getContent());
		articleBody.setIndexId(opSample.getIndexId());
		articleBody.setLanguage(opSample.getLang().getLang());
		articleBody.setType(opSample.getType().getType());
		articleBody.setTips(opSample.getTips());
		articleBody.setTipsColor(opSample.getTipsColor());
		if ( opSample.getDel() != null ){
			articleBody.setDel(opSample.getDel().getFlag());
		}
		return articleBody;
	}
	
	private ArticleVideo convert(MisArticleVideo video){
		ArticleVideo articleVideo = new ArticleVideo();
		articleVideo.setArticleId(video.getArticleId());
		articleVideo.setId(video.getId());
		articleVideo.setLanguage(video.getLang().getLang());
		articleVideo.setSort(video.getIndex());
		articleVideo.setVideoId(video.getVideoId());
		if ( video.getDel() != null ){
			articleVideo.setDel(video.getDel().getFlag());
		}
		return articleVideo;
	}
	
	private ArticleImage convert(MisArticleImage image) {
		ArticleImage articleImage = new ArticleImage();
		articleImage.setArticleId(image.getArticleId());
		articleImage.setId(image.getId());
		articleImage.setLanguage(image.getLang().getLang());
		articleImage.setSort(image.getIndex());
		articleImage.setImageId(image.getImageId());
		if ( image.getDel() != null ){
			articleImage.setDel(image.getDel().getFlag());
		}
		return articleImage;
	}
	
	private ArticleRelate convert(MisArticleRelate relate){
		ArticleRelate articleRelate = new ArticleRelate();
		articleRelate.setArticleId(relate.getArticleId());
		articleRelate.setId(relate.getId());
		articleRelate.setRelateArticleId(relate.getRelateArticleId());
		articleRelate.setLanguage(relate.getLang().getLang());
		articleRelate.setSort(relate.getIndex());
		if ( relate.getDel() != null ){
			articleRelate.setDel(relate.getDel().getFlag());
		}
		return articleRelate;
	}
	
	private ArticleRelateVideo convert(MisArticleRelateVideo video){
		ArticleRelateVideo relateVideo = new ArticleRelateVideo();
		relateVideo.setArticleId(video.getArticleId());
		relateVideo.setLanguage(video.getLang().getLang());
		relateVideo.setId(video.getId());
		relateVideo.setSort(video.getIndex());
		relateVideo.setRelateVideoId(video.getRelateVideoId());
		if ( video.getDel() != null ){
			relateVideo.setDel(video.getDel().getFlag());
		}
		return relateVideo;
	}
	
	private ArticleTag convert(MisArticleTag tag){
		ArticleTag articleTag = new ArticleTag();
		articleTag.setArticleId(tag.getArticleId());
		articleTag.setLanguage(tag.getLang().getLang());
		articleTag.setTagId(tag.getTagId());
		if ( tag.getDel() != null ){
			articleTag.setDel(tag.getDel().getFlag());
		}
		return articleTag;
	}
	
	private MisArticleVideo convert(ArticleVideo video){
		MisArticleVideo misVideo = new MisArticleVideo();
		misVideo.setArticleId(video.getArticleId());
		misVideo.setId(video.getId());
		misVideo.setIndex(video.getSort());
		misVideo.setVideoId(video.getVideoId());
		misVideo.setDel(DelFlag.parse(video.getDel()));
		return misVideo;
	}
	
	private MisArticleImage convert(ArticleImage image) {
		MisArticleImage misImage = new MisArticleImage();
		misImage.setArticleId(image.getArticleId());
		misImage.setId(image.getId());
		misImage.setIndex(image.getSort());
		misImage.setImageId(image.getImageId());
		misImage.setDel(DelFlag.parse(image.getDel()));
		return misImage;
	}
	
	private MisArticleRelate convert(ArticleRelate relate){
		MisArticleRelate misRelate = new MisArticleRelate();
		misRelate.setArticleId(relate.getArticleId());
		misRelate.setId(relate.getId());
		misRelate.setIndex(relate.getSort());
		misRelate.setRelateArticleId(relate.getRelateArticleId());
		misRelate.setDel(DelFlag.parse(relate.getDel()));
		return misRelate;
	}
	
	private MisArticleRelateVideo convert(ArticleRelateVideo video){
		MisArticleRelateVideo v = new MisArticleRelateVideo();
		v.setArticleId(video.getArticleId());
		v.setId(video.getId());
		v.setIndex(video.getSort());
		v.setRelateVideoId(video.getRelateVideoId());
		v.setDel(DelFlag.parse(video.getDel()));
		return v;
	}
	
	private MisArticleTag convert(ArticleTag articleTag){
		MisArticleTag misTag = new MisArticleTag();
		misTag.setArticleId(articleTag.getArticleId());
		misTag.setId(articleTag.getId());
		misTag.setLang(Lang.parse(articleTag.getLanguage()));
		misTag.setTagId(articleTag.getTagId());
		misTag.setDel(DelFlag.parse(articleTag.getDel()));
		return misTag;
	}
	
	/**
	 * 去掉回车变成<br/>
	 * @param content
	 * @return
	 */
	private String replaceEnterAsBr(String content){
		return content.replace("\n", "<br/>").replace("\r\n", "<br/>");
	}
	
	/**
	 * /resource/{bookmode}/{lang}/{type}/{name}/download
	 * @param conntent
	 * @return
	 */
	private String replaceImagePath(String content, int siteId, String lang){
		StringBuilder builder = new StringBuilder();
		String lines[] = content.split("<br/>");
		if ( lines != null && lines.length > 0 ){
			for ( String line : lines ){
				String strLine = line;
				if ( line.endsWith("png") || line.endsWith("jpg") ){
					strLine = "<img src=\"/support/res/" + siteId + "/" + lang + "/material/pic/" + line + "\" />" ;
				}
				builder.append("<p>" + strLine + "</p>");
			}
		}
		return builder.toString();
	}
	
	
	///////////////////////////////////////////////////////
	// delete
	
	private void deleteArtile(int id){
		Article article = articleDao.selectById(id);
		if ( article != null ){
			article.setDel(DelFlag.Del.getFlag());
			articleDao.updateByPrimaryKey(article);
			List<ArticleIndex> index = articleIndexDao.selectByArticleIdAndDel(id, DelFlag.UNDel.getFlag());
			index.forEach(e -> {
				e.setDel(DelFlag.Del.getFlag());
				e.setUpdateAt(new Date());
				articleIndexDao.updateByPrimaryKey(e);
			});
			List<ArticleBody> articleBody = articleBodyDao.selectByArticleIdAndDel(id, DelFlag.UNDel.getFlag());
			articleBody.forEach(e -> {
				e.setDel(DelFlag.Del.getFlag());
				e.setUpdateAt(new Date());
				articleBodyDao.updateByPrimaryKey(e);
			});
			List<ArticleVideo> articleVideo = articleVideoDao.selectByArticleIdAndDel(id, DelFlag.UNDel.getFlag());
			articleVideo.forEach(e -> {
				e.setDel(DelFlag.Del.getFlag());
				e.setUpdateAt(new Date());
				articleVideoDao.updateByPrimaryKey(e);
			});
			List<ArticleRelate> articleRelate = articleRelateDao.selectByArticleIdAndDel(id, DelFlag.UNDel.getFlag());
			articleRelate.forEach(e -> {
				e.setDel(DelFlag.Del.getFlag());
				e.setUpdateAt(new Date());
				articleRelateDao.updateByPrimaryKey(e);
			});
			List<ArticleRelateVideo> articleRelateVideo = articleRelateVideoDao.selectByArticleIdAndDel(id, DelFlag.UNDel.getFlag());
			articleRelateVideo.forEach(e -> {
				e.setDel(DelFlag.Del.getFlag());
				e.setUpdateAt(new Date());
				articleRelateVideoDao.updateByPrimaryKey(e);
			});
			List<ArticleTag> articleTag = articleTagDao.selectByArticleIdAndDel(id, DelFlag.UNDel.getFlag());
			articleTag.forEach(e -> {
				e.setDel(DelFlag.Del.getFlag());
				e.setUpdateAt(new Date());
				articleTagDao.updateByPrimaryKey(e);
			});
		}
	}
	
	private void deleteFlow(int id){
		ArticleIndex index = articleIndexDao.selectById(id);
		if ( index != null ){
			index.setDel(DelFlag.UNDel.getFlag());
			articleIndexDao.updateByPrimaryKey(index);
		}
	}
	
	private void deleteOp(int id){
		ArticleBody articleBody = articleBodyDao.selectById(id);
		if ( articleBody != null ){
			articleBody.setDel(DelFlag.UNDel.getFlag());
			articleBodyDao.updateByPrimaryKey(articleBody);
		}
	}
	
	private void deleteVideo(int id){
		ArticleVideo articleVideo = articleVideoDao.selectById(id);
		if ( articleVideo != null ){
			articleVideo.setDel(DelFlag.UNDel.getFlag());
			articleVideoDao.insert(articleVideo);
		}
	}
	
	private void deleteRelate(int id){
		ArticleRelate relate = articleRelateDao.selectById(id);
		if ( relate != null ){
			relate.setDel(DelFlag.UNDel.getFlag());
			articleRelateDao.updateByPrimaryKey(relate);
		}
	}
	
	private void deleteRelateVideo(int id){
		ArticleRelateVideo video = articleRelateVideoDao.selectById(id);
		if ( video != null ){
			video.setDel(DelFlag.UNDel.getFlag());
			articleRelateVideoDao.updateByPrimaryKey(video);
		}
	}
	
	private void deleteTag(int id){
		ArticleTag tag = articleTagDao.selectById(id);
		if ( tag != null ){
			tag.setDel(DelFlag.UNDel.getFlag());
			articleTagDao.updateByPrimaryKey(tag);
		}
	}
	
	///////////////////////////////////////////////////////
	// sync table
	
	private void syncArticleImage(int articleId, List<MisArticleImage> misArticleImages, Lang lang) {
		List<ArticleImage> articleImages = articleImageDao.selectByArticleId(articleId, DelFlag.UNDel.getFlag());
		List<ArticleImage> insertQueue = new ArrayList<>();
		List<ArticleImage> updateQueue = new ArrayList<>();
		List<ArticleImage> deleteQueue = new ArrayList<>();
		Map<Integer, ArticleImage> articleIds = articleImages.stream().collect(Collectors.toMap(ArticleImage::getId, Function.identity(), (v1, v2) -> v1));
		for ( MisArticleImage misArticleImage : misArticleImages ){
			misArticleImage.setLang(lang);
			if ( misArticleImage.getId() <= 0 ){
				misArticleImage.setArticleId(articleId);
				insertQueue.add(convert(misArticleImage));
			} else {
				updateQueue.add(convert(misArticleImage));
				if ( articleIds.get(misArticleImage.getId()) != null){
					articleIds.put(misArticleImage.getId(), null);
				}
			}
		}
		for ( Integer key : articleIds.keySet() ){
			if ( articleIds.get(key) != null ){
				deleteQueue.add(articleIds.get(key));
			}
		}
		// insert
		insertQueue.forEach(e -> {
			e.setDel(DelFlag.UNDel.getFlag());
			articleImageDao.insert(e);
		});
		// update
		updateQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			e.setArticleId(articleId);
			articleImageDao.updateByPrimaryKey(e);
		});
		// delete
		deleteQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			e.setDel(DelFlag.Del.getFlag());
			articleImageDao.updateByPrimaryKey(e);
		});
	}
	
	private void syncArticleVideo(int articleId, List<MisArticleVideo> misAritcleVideos, Lang lang){
		List<ArticleVideo> articleVideos = articleVideoDao.selectByArticleId(articleId, DelFlag.UNDel.getFlag());
		List<ArticleVideo> insertQueue = new ArrayList<>();
		List<ArticleVideo> updateQueue = new ArrayList<>();
		List<ArticleVideo> deleteQueue = new ArrayList<>();
		Map<Integer, ArticleVideo> articleIds = articleVideos.stream().collect(Collectors.toMap(ArticleVideo::getId, Function.identity(), (v1, v2) -> v1));
		for ( MisArticleVideo misArticleVideo : misAritcleVideos ){
			misArticleVideo.setLang(lang);
			if ( misArticleVideo.getId() <= 0 ){
				misArticleVideo.setArticleId(articleId);
				insertQueue.add(convert(misArticleVideo));
			} else {
				updateQueue.add(convert(misArticleVideo));
				if ( articleIds.get(misArticleVideo.getId()) != null){
					articleIds.put(misArticleVideo.getId(), null);
				}
			}
		}
		for ( Integer key : articleIds.keySet() ){
			if ( articleIds.get(key) != null ){
				deleteQueue.add(articleIds.get(key));
			}
		}
		// insert
		insertQueue.forEach(e -> {
			e.setDel(DelFlag.UNDel.getFlag());
			articleVideoDao.insert(e);
		});
		// update
		updateQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			e.setArticleId(articleId);
			articleVideoDao.updateByPrimaryKey(e);
		});
		// delete
		deleteQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			e.setDel(DelFlag.Del.getFlag());
			articleVideoDao.updateByPrimaryKey(e);
		});
	}
	
	private void syncOpSample(int articleId, List<MisArticleOpSample> opSamplesWithFlowId, List<MisArticleOpSample> opSamplesWithNoFlowId, Lang lang){
		List<ArticleBody> articleBody = articleBodyDao.selectByArticleIdAndDel(articleId, DelFlag.UNDel.getFlag());
		List<ArticleBody> insertQueue = new ArrayList<>();
		opSamplesWithNoFlowId.forEach(e -> {
			e.setArticleId(articleId);
			e.setLang(lang);
			insertQueue.add(convert(e));
		});
		List<ArticleBody> updateQueue = new ArrayList<>();
		List<ArticleBody> deleteQueue = new ArrayList<>();
		Map<Integer, ArticleBody> articleBodies = articleBody.stream().collect(Collectors.toMap(ArticleBody::getId, Function.identity(), (v1, v2) -> v1));
		for ( MisArticleOpSample misOpSample : opSamplesWithFlowId ){
			misOpSample.setLang(lang);
			if ( misOpSample.getId() <= 0 ){
				misOpSample.setArticleId(articleId);
				insertQueue.add(convert(misOpSample));
			} else {
				updateQueue.add(convert(misOpSample));
				if ( articleBodies.get(misOpSample.getId()) != null){
					articleBodies.put(misOpSample.getId(), null);
				}
			}
		}
		for ( Integer key : articleBodies.keySet() ){
			if ( articleBodies.get(key) != null ){
				deleteQueue.add(articleBodies.get(key));
			}
		}
		// insert
		insertQueue.forEach(e -> {
			e.setDel(DelFlag.UNDel.getFlag());
			articleBodyDao.insert(e);
		});
		// update
		updateQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			articleBodyDao.updateByPrimaryKey(e);
		});
		// delete
		deleteQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			e.setDel(DelFlag.Del.getFlag());
			articleBodyDao.updateByPrimaryKey(e);
		});
	}
	
	private void syncFlowDesp(int articleId, List<MisArticleFlowDescription> flow, Lang lang){
		List<ArticleIndex> articleIndexes = articleIndexDao.selectByArticleIdAndDel(articleId, DelFlag.UNDel.getFlag());
		List<ArticleIndex> insertQueue = new ArrayList<>();
		List<ArticleIndex> updateQueue = new ArrayList<>();
		List<ArticleIndex> deleteQueue = new ArrayList<>();
		Map<Integer, ArticleIndex> articleIndexIds = articleIndexes.stream().collect(Collectors.toMap(ArticleIndex::getId, Function.identity(), (v1, v2) -> v1));
		for ( MisArticleFlowDescription misFlowDesc : flow ){
			misFlowDesc.setLang(lang);
 			if ( misFlowDesc.getId() <= 0 ){
				misFlowDesc.setArticleId(articleId);
				insertQueue.add(convert(misFlowDesc));
			} else {
				updateQueue.add(convert(misFlowDesc));
				if ( articleIndexIds.get(misFlowDesc.getId()) != null){
					articleIndexIds.put(misFlowDesc.getId(), null);
				}
			}
		}
		for ( Integer key : articleIndexIds.keySet() ){
			if ( articleIndexIds.get(key) != null ){
				deleteQueue.add(articleIndexIds.get(key));
			}
		}
		// insert
		insertQueue.forEach(e -> {
			e.setDel(DelFlag.UNDel.getFlag());
			articleIndexDao.insert(e);
			flow.forEach(f -> {
				if ( f.getTilte().equals(e.getIndexName()) ){
					f.setId(e.getId());
				}
			});
		});
		// update
		updateQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			articleIndexDao.updateByPrimaryKey(e);
		});
		// delete
		deleteQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			e.setDel(DelFlag.Del.getFlag());
			articleIndexDao.updateByPrimaryKey(e);
		});
	}
	
	private void syncRelate(int articleId, List<MisArticleRelate> msiArticleRelate, Lang lang){
		List<ArticleRelate> articleRelate = articleRelateDao.selectByArticleIdAndDel(articleId, DelFlag.UNDel.getFlag());
		List<ArticleRelate> insertQueue = new ArrayList<>();
		List<ArticleRelate> updateQueue = new ArrayList<>();
		List<ArticleRelate> deleteQueue = new ArrayList<>();
		Map<Integer, ArticleRelate> articleRelateIds= articleRelate.stream().collect(Collectors.toMap(ArticleRelate::getId, Function.identity(), (v1, v2) -> v1));
		for ( MisArticleRelate misRelate : msiArticleRelate ){
			misRelate.setLang(lang);
			if ( misRelate.getId() <= 0 ){
				misRelate.setArticleId(articleId);
				insertQueue.add(convert(misRelate));
			} else {
				updateQueue.add(convert(misRelate));
				if ( articleRelateIds.get(misRelate.getId()) != null){
					articleRelateIds.put(misRelate.getId(), null);
				}
			}
		}
		for ( Integer key : articleRelateIds.keySet() ){
			if ( articleRelateIds.get(key) != null ){
				deleteQueue.add(articleRelateIds.get(key));
			}
		}
		// insert
		insertQueue.forEach(e -> {
			e.setDel(DelFlag.UNDel.getFlag());
			articleRelateDao.insert(e);
		});
		// update
		updateQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			articleRelateDao.updateByPrimaryKey(e);
		});
		// delete
		deleteQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			e.setDel(DelFlag.Del.getFlag());
			articleRelateDao.updateByPrimaryKey(e);
		});
	}
	
	private void syncRelateVideo(int articleId, List<MisArticleRelateVideo> msiArticleRelateVideo, Lang lang){
		List<ArticleRelateVideo> articleRelateVideo = articleRelateVideoDao.selectByArticleIdAndDel(articleId, DelFlag.UNDel.getFlag());
		List<ArticleRelateVideo> insertQueue = new ArrayList<>();
		List<ArticleRelateVideo> updateQueue = new ArrayList<>();
		List<ArticleRelateVideo> deleteQueue = new ArrayList<>();
		Map<Integer, ArticleRelateVideo> articleRelateVideoIds = articleRelateVideo.stream().collect(Collectors.toMap(ArticleRelateVideo::getId, Function.identity(), (v1, v2) -> v1));
		for ( MisArticleRelateVideo misRelateVideo : msiArticleRelateVideo ){
			misRelateVideo.setLang(lang);
			if ( misRelateVideo.getId() <= 0 ){
				misRelateVideo.setArticleId(articleId);
				insertQueue.add(convert(misRelateVideo));
			} else {
				ArticleRelateVideo updater = convert(misRelateVideo);
				updateQueue.add(updater);
				if ( articleRelateVideoIds.get(misRelateVideo.getId()) != null){
					updater.setCreateAt(articleRelateVideoIds.get(misRelateVideo.getId()).getCreateAt());
					articleRelateVideoIds.put(misRelateVideo.getId(), null);
				}
			}
		}
		for ( Integer key : articleRelateVideoIds.keySet() ){
			if ( articleRelateVideoIds.get(key) != null ){
				deleteQueue.add(articleRelateVideoIds.get(key));
			}
		}
		// insert
		insertQueue.forEach(e -> {
			e.setDel(DelFlag.UNDel.getFlag());
			articleRelateVideoDao.insert(e);
		});
		// update
		updateQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			articleRelateVideoDao.updateByPrimaryKey(e);
		});
		// delete
		deleteQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			e.setDel(DelFlag.Del.getFlag());
			articleRelateVideoDao.updateByPrimaryKey(e);
		});
	}	
	
	private void syncTag(int articleId, List<MisArticleTag> msiArticleTag, Lang lang){
		List<ArticleTag> articleRelateVideo = articleTagDao.selectByArticleIdAndDel(articleId, DelFlag.UNDel.getFlag());
		List<ArticleTag> insertQueue = new ArrayList<>();
		List<ArticleTag> updateQueue = new ArrayList<>();
		List<ArticleTag> deleteQueue = new ArrayList<>();
		Map<Integer, ArticleTag> articleTagIds = articleRelateVideo.stream().collect(Collectors.toMap(ArticleTag::getId, Function.identity(), (v1, v2) -> v1));
		for ( MisArticleTag tag : msiArticleTag ){
			tag.setLang(lang);
			if ( tag.getId() <= 0 ){
				tag.setArticleId(articleId);
				insertQueue.add(convert(tag));
			} else {
				updateQueue.add(convert(tag));
				if ( articleTagIds.get(tag.getId()) != null){
					articleTagIds.put(tag.getId(), null);
				}
			}
		}
		for ( Integer key : articleTagIds.keySet() ){
			if ( articleTagIds.get(key) != null ){
				deleteQueue.add(articleTagIds.get(key));
			}
		}
		// insert
		insertQueue.forEach(e -> {
			e.setDel(DelFlag.UNDel.getFlag());
			articleTagDao.insert(e);
		});
		// update
		updateQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			articleTagDao.updateByPrimaryKey(e);
		});
		// delete
		deleteQueue.forEach(e -> {
			e.setUpdateAt(new Date());
			e.setDel(DelFlag.Del.getFlag());
			articleTagDao.updateByPrimaryKey(e);
		});
	}
	
	
	///////////////////////////////////////////////////////
	// get list
	
	private List<MisArticleFlowDescription> getExcelFlowByArticleId(int articleId){
		List<ArticleIndex> indexes = articleIndexDao.selectByArticleIdAndDel(articleId, DelFlag.UNDel.getFlag());
		List<ArticleBody> body = articleBodyDao.selectByArticleIdAndDel(articleId, DelFlag.UNDel.getFlag());
		List<MisArticleFlowDescription> result = new ArrayList<>();
		List<MisArticleOpSample> opSample = new ArrayList<>();
		indexes.forEach(e -> result.add(convert(e)));
		body.forEach(e -> opSample.add(convert(e)));
		result.forEach(e -> {
			for ( ArticleBody ab : body ){
				if ( ab.getIndexId() == e.getId()){
					e.getOpSamples().add(convert(ab));
				}
			}
		});
		return result;
	}
	
	
	private List<MisArticleFlowDescription> getFlowByArticleId(int articleId){
		List<ArticleIndex> indexes = articleIndexDao.selectByArticleIdAndDel(articleId, DelFlag.UNDel.getFlag());
		List<ArticleBody> body = articleBodyDao.selectByArticleIdAndDel(articleId, DelFlag.UNDel.getFlag());
		List<MisArticleFlowDescription> result = new ArrayList<>();
		List<MisArticleOpSample> opSample = new ArrayList<>();
		indexes.forEach(e -> result.add(convert(e)));
		body.forEach(e -> opSample.add(convert(e)));
		result.forEach(e -> {
			for ( ArticleBody ab : body ){
				if ( ab.getIndexId() == e.getId()){
					List<MisArticleOpSample> opSamples = new ArrayList<>();
					opSamples.add(convert(ab));
					e.setOpSamples(opSamples);
					break;
				}
			}
		});
		return result;
	}
	
	private List<MisArticleVideo> getVideoByArticleId(int articleId){
		List<ArticleVideo> videos = articleVideoDao.selectByArticleId(articleId, DelFlag.UNDel.getFlag());
		List<MisArticleVideo> result = new ArrayList<>();
		videos.forEach(e -> result.add(convert(e)));
		return result;
	}
	
	private List<MisArticleImage> getImageByArticleId(int articleId){
		List<ArticleImage> images = articleImageDao.selectByArticleId(articleId, DelFlag.UNDel.getFlag());
		List<MisArticleImage> result = new ArrayList<>();
		images.forEach(e -> result.add(convert(e)));
		return result;
	}
	
	private List<MisArticleRelate> getRelateByArticleId(int articleId){
		List<ArticleRelate> articleRelate = articleRelateDao.selectByArticleIdAndDel(articleId, DelFlag.UNDel.getFlag());
		List<Integer> articleRelateIds = articleRelate.stream().map(e -> e.getRelateArticleId()).collect(Collectors.toList());
		List<Article> relateTitles = articleDao.selectByIds(articleRelateIds);
		Map<Integer, Article> relateTitleMapping = relateTitles.stream().collect(Collectors.toMap(Article::getId, Function.identity()));
		List<MisArticleRelate> result = new ArrayList<>();
		articleRelate.forEach(e -> {
			MisArticleRelate misRelate = convert(e);
			if ( relateTitleMapping.get(e.getRelateArticleId()) != null ){
				misRelate.setRelateArticleTitle(relateTitleMapping.get(e.getRelateArticleId()).getTitle());
			}
			result.add(misRelate);
		});
			
		return result;
	}
	
	private List<MisArticleRelateVideo> getRelateVideoByArticleId(int articleId){
		List<ArticleRelateVideo> relateVideo = articleRelateVideoDao.selectByArticleId(articleId, DelFlag.UNDel.getFlag());
		List<MisArticleRelateVideo> result = new ArrayList<>();
		relateVideo.forEach(e -> result.add(convert(e)));
		return result;
	}
	
	private List<MisArticleTag> getArticleTag(int articleId){
		List<ArticleTag> tags = articleTagDao.selectByArticleIdAndDel(articleId, DelFlag.UNDel.getFlag());
		List<MisArticleTag> misTags = new ArrayList<>();
		tags.forEach(e -> misTags.add(convert(e)));
		return misTags;
	}
	
	
	///////////////////////////////////////////////////////
	// interface
	
	
	public MisArticles getExcelArticles(MisArticleFilter filter, boolean detail){
		logger.info("[getArticles] begin");
		if ( filter != null ){
			MisArticles misArticles = new MisArticles();
			List<ArticleUser> articleUser = articleDao.selectArticleUserByFilter(filter);
			if ( !articleUser.isEmpty() ){
				int count = articleDao.selectArticleUserCountByFilter(filter);
				articleUser.forEach(artUser -> {
					MisArticle msA = convert(artUser);
					// 视频信息必须取得
					// 视频
					msA.setArticleVideo(getVideoByArticleId(msA.getId()));
					// 相关视频
					//msA.setRelatedVideo(getRelateVideoByArticleId(msA.getId()));
					if ( detail ){
						// 流程简章
						msA.setFlowDescription(getExcelFlowByArticleId(msA.getId()));
						// 相关文章
						//msA.setRelatedArticle(getRelateByArticleId(msA.getId()));
						// tag
						//msA.setTags(getArticleTag(msA.getId()));
					}
					misArticles.getArticles().add(msA);
				});
				misArticles.setTotalSize(count);
			}
			return misArticles;
		}
		return null;
	}
	
	/**
	 *  查找文章
	 */
	@Override
	public MisArticles getArticles(MisArticleFilter filter, boolean detail) {
		logger.info("[getArticles] begin");
		if ( filter != null ){
			MisArticles misArticles = new MisArticles();
			List<ArticleUser> articleUser = articleDao.selectArticleUserByFilter(filter);
			if ( !articleUser.isEmpty() ){
				int count = articleDao.selectArticleUserCountByFilter(filter);
					articleUser.forEach(artUser -> {
						MisArticle msA = convert(artUser);
						// 视频信息必须取得
						// 视频
						msA.setArticleVideo(getVideoByArticleId(msA.getId()));
						// 相关视频
						msA.setRelatedVideo(getRelateVideoByArticleId(msA.getId()));
						if ( detail ){
							// 流程简章
							msA.setFlowDescription(getFlowByArticleId(msA.getId()));
							// 相关文章
							msA.setRelatedArticle(getRelateByArticleId(msA.getId()));
							// tag
							msA.setTags(getArticleTag(msA.getId()));
						}
						misArticles.getArticles().add(msA);
					});
				misArticles.setTotalSize(count);
			}
			return misArticles;
		}
		return null;
	}
	/**
	 *  新建/更新文章
	 */
	@Override
	public void addArticle(MisArticle article) {
		if ( article != null ){
			boolean isUpdated = false;
			if ( article.getId() <= 0 ){
				Article a = convert(article);
				a.setDel(DelFlag.UNDel.getFlag());
				articleDao.insert(a);
				article.setId(a.getId());
				isUpdated = true;
			} else {
				Article a = articleDao.selectById(article.getId());
				if ( a != null && a.getDel() == DelFlag.UNDel.getFlag() ){
					if ( article.getSummary() != null ){
						a.setAbs(article.getSummary());
					}
					if ( article.getArticleNo() != null ){
						a.setArticleNo(article.getArticleNo());
					}
					if ( article.getFileName() != null ){
						a.setFileName(article.getFileName());
					}
					if ( article.getRemark() != null ){
						a.setRemark(article.getRemark());
					}
					if ( article.getTitle() != null ){
						a.setTitle(article.getTitle());
					}
					a.setUpdateUserId(article.getUpdateById());
					a.setUpdateUserName(article.getUpdateBy());
					a.setUpdateAt(new Date());
					articleDao.updateByPrimaryKey(a);
					isUpdated = true;
				}
			}
			if ( isUpdated ){
				// 新建或则更新其他关联信息
				// 同步数据
				if ( article.getArticleVideo() != null ){
					syncArticleVideo(article.getId(), article.getArticleVideo(), article.getLang());
				}
				// 同步图片
				if ( article.getArticleImage() != null ) {
					syncArticleImage(article.getId(), article.getArticleImage(), article.getLang());
				}
				// 
				if ( article.getFlowDescription() != null ){
					List<MisArticleOpSample> opSampleWithNoFlowId = new ArrayList<>();
					List<MisArticleOpSample> opSampleWithFlowId = new ArrayList<>();
					syncFlowDesp(article.getId(), article.getFlowDescription(), article.getLang());
					article.getFlowDescription().forEach(e -> {
						if ( e.getOpSamples() != null ){
							e.getOpSamples().forEach(opS -> {
								opS.setIndexId(e.getId());
								if ( opS.getIndexId() > 0 ){
									opSampleWithFlowId.add(opS);
								} else {
									opSampleWithNoFlowId.add(opS);
								}
							});
						}
					});
					syncOpSample(article.getId(), opSampleWithFlowId, opSampleWithNoFlowId, article.getLang());
				}
				if ( article.getRelatedArticle() != null ){
					syncRelate(article.getId(), article.getRelatedArticle(), article.getLang());
				}
				if ( article.getRelatedVideo() != null ){
					syncRelateVideo(article.getId(), article.getRelatedVideo(), article.getLang());
				}
				if ( article.getTags() != null ){
					syncTag(article.getId(), article.getTags(), article.getLang());
				}
			}
			
		}
	}
	/**
	 *  新建/更新流程简述
	 */
	@Override
	public void addFlowDescription(MisArticleFlowDescription description) {
		if ( description != null ){
			if ( description.getId() <= 0 ){
				ArticleIndex index = convert(description);
				index.setDel(DelFlag.UNDel.getFlag());
				articleIndexDao.insert(index);
			} else {
				ArticleIndex index= articleIndexDao.selectById(description.getId());
				if ( index != null && index.getDel() == DelFlag.UNDel.getFlag() ){
					index.setIndexName(description.getTilte());
					index.setUpdateAt(new Date());
					articleIndexDao.updateByPrimaryKey(index);
				}
			}
		}
	}
	/**
	 *  新建/更新操作规范
	 */
	@Override
	public void addOpSample(MisArticleOpSample opSample) {
		if ( opSample != null ){
			if ( opSample.getId() <= 0 ){
				ArticleBody ab = convert(opSample);
				ab.setDel(DelFlag.UNDel.getFlag());
				articleBodyDao.insert(ab);
			} else {
				ArticleBody ab = articleBodyDao.selectById(opSample.getId());
				if ( ab != null ){
					ab.setContent(opSample.getContent());
					ab.setUpdateAt(new Date());
					articleBodyDao.updateByPrimaryKey(ab);
				}
			}
		}
	}
	/**
	 *  新建/更新视频
	 */
	@Override
	public void addVideo(MisArticleVideo video) {
		if ( video != null ){
			if ( video.getId() <= 0 ){
				ArticleVideo articleVideo = convert(video);
				articleVideo.setDel(DelFlag.UNDel.getFlag());
				articleVideoDao.insert(articleVideo);
			} else {
				ArticleVideo articleVideo = articleVideoDao.selectById(video.getId());
				if ( articleVideo != null ){
					articleVideo.setSort(video.getIndex());
					articleVideo.setVideoId(video.getVideoId());
					articleVideo.setUpdateAt(new Date());
					articleVideoDao.updateByPrimaryKey(articleVideo);
				}
			}
		}
	}
	/**
	 *  新建/更新相关文章
	 */
	@Override
	public void addRelateArticle(MisArticleRelate relateArticle) {
		if ( relateArticle != null ){
			if ( relateArticle.getId() <= 0 ){
				ArticleRelate articleRelate = convert(relateArticle);
				articleRelate.setDel(DelFlag.UNDel.getFlag());
				articleRelateDao.insert(articleRelate);
			} else {
				ArticleRelate articleRelate = articleRelateDao.selectById(relateArticle.getId());
				if ( articleRelate != null ){
					articleRelate.setRelateArticleId(relateArticle.getRelateArticleId());
					articleRelate.setSort(relateArticle.getIndex());
					articleRelate.setUpdateAt(new Date());
					articleRelateDao.updateByPrimaryKey(articleRelate);
				}
			}
		}
	}
	/**
	 *  新建/更新相关文章
	 */
	@Override
	public void addRelateVideo(MisArticleRelateVideo relateVideo) {
		if ( relateVideo != null ){
			if ( relateVideo.getId() <= 0 ){
				ArticleRelateVideo relativeVideo = convert(relateVideo);
				relativeVideo.setDel(DelFlag.UNDel.getFlag());
				articleRelateVideoDao.insert(relativeVideo);
			} else {
				ArticleRelateVideo arVideo = articleRelateVideoDao.selectById(relateVideo.getId());
				if ( arVideo != null ){
					arVideo.setRelateVideoId(relateVideo.getRelateVideoId());
					arVideo.setSort(relateVideo.getIndex());
					arVideo.setUpdateAt(new Date());
					articleRelateVideoDao.insert(arVideo);
				}
			}
		}
	}
	/**
	 *  新建/更新tag
	 */
	@Override
	public void addRelateTag(MisArticleTag tag) {
		if ( tag != null ){
			if ( tag.getId() <= 0 ){
				ArticleTag articleTag = convert(tag);
				articleTag.setDel(DelFlag.UNDel.getFlag());
				articleTagDao.insert(articleTag);
			} else {
				ArticleTag articleTag = articleTagDao.selectById(tag.getId());
				if ( articleTag != null ){
					articleTag.setTagId(tag.getTagId());
					articleTag.setUpdateAt(new Date());
					articleTagDao.updateByPrimaryKey(articleTag);
				}
			}
		}	
	}

	@Override
	public void deleteArticle(int id, MisArticleType type) {
		if ( type != null && id > 0 ){
			switch ( type ){
			case Article:
				deleteArtile(id);
				break;
			case ArticleFlow:
				deleteFlow(id);
				break;
			case ArticleOp:
				deleteOp(id);
				break;
			case ArticleVideo:
				deleteVideo(id);
				break;
			case ArticleRelate:
				deleteRelate(id);
				break;
			case ArticleRelateVideo:
				deleteRelateVideo(id);
				break;
			case ArticleTag:
				deleteTag(id);
				break;
			default:
			}
		}
	}

	@Override
	public MisArticle getArticle(int articleId, boolean detail) {
		if ( articleId > 0 ){
			Article article = articleDao.selectById(articleId);
			if ( article != null ){
				MisArticle msA = convert(article);
				if ( detail ){
					// 流程简章
					msA.setFlowDescription(getFlowByArticleId(msA.getId()));
					// 视频
					msA.setArticleVideo(getVideoByArticleId(msA.getId()));
					// 图片
					msA.setArticleImage(getImageByArticleId(msA.getId()));
					// 相关文章
					msA.setRelatedArticle(getRelateByArticleId(msA.getId()));
					// 相关视频
					msA.setRelatedVideo(getRelateVideoByArticleId(msA.getId()));
					// tag
					msA.setTags(getArticleTag(msA.getId()));
				}
				return msA;
			}
		}
		return null;
	}

	@Override
	public List<MisArticle> getArticles(List<Integer> articleIds, boolean detail) {
		List<MisArticle> misArticles = new ArrayList<>();
		if ( articleIds != null ){
			List<Article> articles = articleDao.selectByIds(articleIds);
			if ( !detail ) {
				articles.forEach(e -> misArticles.add(convert(e)));
			} else {
				articles.forEach(e -> {
					MisArticle msA = convert(e);
					if ( detail ){
						// 流程简章
						msA.setFlowDescription(getFlowByArticleId(msA.getId()));
						// 视频
						msA.setArticleVideo(getVideoByArticleId(msA.getId()));
						// 图片
						msA.setArticleImage(getImageByArticleId(msA.getId()));
						// 相关文章
						msA.setRelatedArticle(getRelateByArticleId(msA.getId()));
						// 相关视频
						msA.setRelatedVideo(getRelateVideoByArticleId(msA.getId()));
						// tag
						msA.setTags(getArticleTag(msA.getId()));
					}
					misArticles.add(msA);
				});
			}
		}
		return misArticles;
	}

	@Override
	public boolean isExsit(int siteId, String lang, String no, String title, String fileName) {
//		int count = articleDao.selectCountByName(no, title, fileName, lang, bookMode.getId());
//		return count > 0 ? true : false;
		return false;
	}

	@Override
	public void createExcelArticles(Map<Integer, List<MisExcelArticle>> artiles, int siteId, Lang lang) {
		if ( artiles != null && siteId > 0 && lang != null ){
			List<MisExcelArticle> newArtiles = new ArrayList<>();
			List<MisExcelArticle> upArtiles = new ArrayList<>();
			for ( Integer key : artiles.keySet() ){
				if ( key.intValue() == 1 ){
					newArtiles.addAll(artiles.get(key));
				} else if ( key.intValue() == 2 ){
					upArtiles.addAll(artiles.get(key));
				} else {
					
				}
			}
			Map<String, MisExcelArticle> newArtilesMap = newArtiles.stream().collect(Collectors.toMap(MisExcelArticle::getArticleNo, Function.identity()));
			Map<String, MisExcelArticle> updateArtilesMap = upArtiles.stream().collect(Collectors.toMap(MisExcelArticle::getArticleNo, Function.identity()));
			List<String> artileNos = new ArrayList<>();
			artileNos.addAll(newArtiles.stream().map(e -> e.getArticleNo()).collect(Collectors.toList()));
			artileNos.addAll(upArtiles.stream().map(e -> e.getArticleNo()).collect(Collectors.toList()));
			if ( !artileNos.isEmpty() ){
				// 找到所有article by artile_no
				List<Article> myArtiles = articleDao.selectByNos(artileNos, siteId, lang.getLang());
				// 检查更新，新建队列
				boolean newIsFound = false;
				boolean updateIsNotFound = false;
				int  upIsFoundSize = 0;
				String errorNo = "";
				for ( Article a : myArtiles ){
					if ( newArtilesMap.get(a.getArticleNo()) != null ){
						newIsFound = true;
						errorNo = a.getArticleNo();
						break;
					}
					if ( updateArtilesMap.get(a.getArticleNo()) == null ){
						updateIsNotFound = true;
						errorNo = a.getArticleNo();
						break;
					}
				}
				if ( newIsFound ){
					throw new RuntimeException("新增的ArticleNo = " + errorNo + "在数据库中已经存在");
				}
				if ( updateIsNotFound ){
					throw new RuntimeException("更新的ArticleNo = " + errorNo + "在数据库中不存在");
				}
				
				Map<String, Article> myArtilesMap = myArtiles.stream().collect(Collectors.toMap(Article::getArticleNo, Function.identity()));
				// 新建队列
				newArtiles.forEach( e -> {
					// 新建文章
					Article art = new Article();
					String abs = replaceEnterAsBr(e.getArticleAbstract());
					art.setAbs(replaceImagePath(abs, siteId, lang.getLang()));
					art.setArticleNo(e.getArticleNo());
					art.setSiteId(siteId);
					art.setLanguage(lang.getLang());
					art.setFileName(e.getArticleNo() + ".html");
					art.setTitle(e.getArticleTitle());
					art.setUpdateUserId(e.getUserId());
					art.setUpdateUserName(e.getUserName());
					art.setUserId(e.getCreator());
					art.setDel(DelFlag.UNDel.getFlag());
					articleDao.insert(art);
					// 新建流程简述
					e.getIndexes().forEach(eIndex -> {
						ArticleIndex ind = new ArticleIndex();
						ind.setArticleId(art.getId());
						ind.setDel(DelFlag.UNDel.getFlag());
						ind.setIndexName(replaceEnterAsBr(eIndex.getIndexName()));
						ind.setLanguage(lang.getLang());
						articleIndexDao.insert(ind);
						eIndex.getArticleBodys().forEach( eBody -> {
							ArticleBody artBody = new ArticleBody();
							artBody.setArticleId(art.getId());
							String op = replaceEnterAsBr(eBody.getOpContent());
							artBody.setContent(replaceImagePath(op, siteId, lang.getLang()));
							artBody.setDel(DelFlag.UNDel.getFlag());
							artBody.setIndexId(ind.getId());
							artBody.setTipsColor("#fdffab");
							artBody.setLanguage(lang.getLang());
							artBody.setTips(replaceImagePath(replaceEnterAsBr(eBody.getOpTips()), siteId, lang.getLang()));
							articleBodyDao.insert(artBody);
						});
					});
					// 新建视频
					e.getVideos().forEach( eVideo -> {
						ArticleVideo artVideo = new ArticleVideo();
						artVideo.setArticleId(art.getId());
						artVideo.setDel(DelFlag.UNDel.getFlag());
						artVideo.setLanguage(lang.getLang());
						artVideo.setVideoId(eVideo.getVideoId());
						articleVideoDao.insert(artVideo);
					});
				});
				// 更新队列
				upArtiles.forEach( e -> {
					Article upArt = myArtilesMap.get(e.getArticleNo());
					String abs = replaceEnterAsBr(e.getArticleAbstract());
					upArt.setAbs(replaceImagePath(abs, siteId, lang.getLang()));
					upArt.setTitle(e.getArticleTitle());
					upArt.setUpdateUserId(e.getUserId());
					upArt.setUpdateUserName(e.getUserName());
					upArt.setUpdateAt(new Date());
					articleDao.updateByPrimaryKey(upArt);
					// 删除流程简述
					articleIndexDao.deleteByArticleId(upArt.getId());
					articleBodyDao.deleteByArticleId(upArt.getId());
					// 删除视频
					articleVideoDao.deleteByArticleId(upArt.getId());
					// 新建流程简述
					e.getIndexes().forEach(eIndex -> {
						ArticleIndex ind = new ArticleIndex();
						ind.setArticleId(upArt.getId());
						ind.setDel(DelFlag.UNDel.getFlag());
						ind.setIndexName(replaceEnterAsBr(eIndex.getIndexName()));
						ind.setLanguage(lang.getLang());
						articleIndexDao.insert(ind);
						eIndex.getArticleBodys().forEach( eBody -> {
							ArticleBody artBody = new ArticleBody();
							artBody.setArticleId(upArt.getId());
							String op = replaceEnterAsBr(eBody.getOpContent());
							artBody.setContent(replaceImagePath(op, siteId, lang.getLang()));
							artBody.setDel(DelFlag.UNDel.getFlag());
							artBody.setIndexId(ind.getId());
							artBody.setTipsColor("#fdffab");
							artBody.setLanguage(lang.getLang());
							String tips = replaceEnterAsBr(eBody.getOpTips());
							artBody.setTips(replaceImagePath(replaceImagePath(tips, siteId, lang.getLang()), siteId, lang.getLang()));
							articleBodyDao.insert(artBody);
						});
					});
					// 新建视频
					e.getVideos().forEach( eVideo -> {
						ArticleVideo artVideo = new ArticleVideo();
						artVideo.setArticleId(upArt.getId());
						artVideo.setDel(DelFlag.UNDel.getFlag());
						artVideo.setLanguage(lang.getLang());
						artVideo.setVideoId(eVideo.getVideoId());
						articleVideoDao.insert(artVideo);
					});
				});
			}
		}
	}

	@Override
	public Map<String, Map<String, Integer>> getSiteIdArticleData(int siteId) {
		if ( siteId > 0 ) {
			Map<String, Map<String, Integer>> results = new HashMap<>();
			List<Article> articles = articleDao.selectActiveBySiteId(siteId);
			articles.forEach( e -> {
				if ( results.get(e.getLanguage()) == null ) {
					results.put(e.getLanguage(), new HashMap<String, Integer>());
				}
				results.get(e.getLanguage()).put(e.getArticleNo(), e.getId());
			});
			return results;
		}
		return new HashMap<>();
	}

	@Override
	public void batchfixCanModify(List<Integer> articleIds, int modify) {
		if ( articleIds == null || articleIds.isEmpty() || modify < 0 ){
			return;
		}
		List<Article> articles = articleDao.selectByIds(articleIds);
		// 找到其他语言对应的articles
		if ( articles.isEmpty() ){
			return;
		}
		List<String> cnArticleNames = articles.stream().map(e -> e.getArticleNo()).collect(Collectors.toList());
		List<Article> jpArticles = articleDao.selectByNos(cnArticleNames, articles.get(0).getSiteId(), Lang.jaJP.getLang());
		List<Article> enArticles = articleDao.selectByNos(cnArticleNames, articles.get(0).getSiteId(), Lang.enUS.getLang());
		List<Article> koArticles = articleDao.selectByNos(cnArticleNames, articles.get(0).getSiteId(), Lang.ko.getLang());
		List<Article> thArticles = articleDao.selectByNos(cnArticleNames, articles.get(0).getSiteId(), Lang.th.getLang());
		List<Article> twArticles = articleDao.selectByNos(cnArticleNames, articles.get(0).getSiteId(), Lang.zhTW.getLang());
		// 处理中文
		articles.forEach(a -> {
			a.setCanModify(modify);
			a.setUpdateAt(new Date());
			articleDao.updateByPrimaryKey(a);
		});
		// 处理日文
		jpArticles.forEach(a -> {
			a.setCanModify(modify);
			a.setUpdateAt(new Date());
			articleDao.updateByPrimaryKey(a);
		});
		// 处理英文
		enArticles.forEach(a -> {
			a.setCanModify(modify);
			a.setUpdateAt(new Date());
			articleDao.updateByPrimaryKey(a);
		});
		// 处理韩文
		koArticles.forEach(a -> {
			a.setCanModify(modify);
			a.setUpdateAt(new Date());
			articleDao.updateByPrimaryKey(a);
		});
		// 处理泰文
		thArticles.forEach(a -> {
			a.setCanModify(modify);
			a.setUpdateAt(new Date());
			articleDao.updateByPrimaryKey(a);
		});
		// 处理繁体字
		twArticles.forEach(a -> {
			a.setCanModify(modify);
			a.setUpdateAt(new Date());
			articleDao.updateByPrimaryKey(a);
		});
	}

	@Override
	public int getArticleCountBySiteIdAndLang(int siteId, Lang lang) {
		if( siteId > 0 || lang == null ){
			return -1;
		}
		int count = articleDao.selectBySiteIdAndLang(siteId, lang.getLang());
		return count;
	}

	@Override
	public void deleteRelateVideoByVideIs(int videoId) {
		if ( videoId > 0 ){
			articleRelateVideoDao.deleteByVideoId(videoId);
		}
		
	}

	@Override
	public void addImage(MisArticleImage image) {
		if ( image != null ){
			if ( image.getId() <= 0 ){
				ArticleImage articleImage = convert(image);
				articleImage.setDel(DelFlag.UNDel.getFlag());
				articleImageDao.insert(articleImage);
			} else {
				ArticleImage articleImage = articleImageDao.selectById(image.getId());
				if ( articleImage != null ){
					articleImage.setSort(image.getIndex());
					articleImage.setImageId(image.getImageId());
					articleImage.setUpdateAt(new Date());
					articleImageDao.updateByPrimaryKey(articleImage);
				}
			}
		}
		
	}

}
